package net.sf.midollo.midlet.common;

import javax.microedition.lcdui.ChoiceGroup;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;

import net.sf.midollo.utils.MidpUtils;
import net.sf.midollo.utils.Utils;

public class ConnectionEditor implements ItemStateListener {

  public static final String PREFIX_SOCKET = "socket://";
  public static final String PREFIX_COMM = "comm:";

  protected Form form;
  protected ChoiceGroup connTypeChoice;
  protected int lastConnType = -1;
  protected String connName;

  public ConnectionEditor(Form form, String connName) {
    this.form = form;
    form.setItemStateListener(this);
    String[] connTypes = new String[] { "Generic", "Socket", "Comm" };
    connTypeChoice = new ChoiceGroup("Connection Type", ChoiceGroup.EXCLUSIVE, connTypes, null);
    form.append(connTypeChoice);
    setValue(connName, true);
  }

  public static ConnectionEditor createForm(String title, String connName) {
    if (title == null)
      title = "Edit Connection";
    Form form = new Form(title);
    return new ConnectionEditor(form, connName);
  }

  public Form getForm() {
    return form;
  }

  public String getValue() {
    int idx = getFirstFieldIndex();
    if (idx >= 0) {
      int connType = connTypeChoice.getSelectedIndex();
      if (connType == 1)
        connName = getSocketValue(idx);
      else if (connType == 2)
        connName = getCommValue(idx);
      else
        connName = getGenericValue(idx);
    }
    return connName;
  }

  public void setValue(String connName) {
    setValue(connName, false);
  }

  protected void setValue(String connName, boolean init) {
    int connType = 0;
    if (connName != null) {
      connName = connName.trim();
      if (connName.startsWith(PREFIX_SOCKET))
        connType = 1;
      else if (connName.startsWith(PREFIX_COMM))
        connType = 2;
    }
    this.connName = connName;
    connTypeChoice.setSelectedIndex(connType, true);
    layout(connType, init);
  }

  protected int getFirstFieldIndex() {
    for (int i = 0; i < form.size(); ++i) {
      if (connTypeChoice == form.get(i))
        return i;
    }
    return -1;
  }

  protected void layout(int connType, boolean init) {
    if (!init) {
      int idx = getFirstFieldIndex();
      if (idx >= 0)
        undoLayout(idx);
    }
    if (connType == 1)
      layoutSocket(connName.substring(PREFIX_SOCKET.length()));
    else if (connType == 2)
      layoutComm(connName.substring(PREFIX_COMM.length()));
    else
      layoutGeneric(connName);
    lastConnType = connType;
  }

  protected void undoLayout(int idx) {
    if (lastConnType == 0)
      undoLayoutGeneric(idx);
    else if (lastConnType == 1)
      undoLayoutSocket(idx);
    else if (lastConnType == 2)
      undoLayoutComm(idx);
  }

  protected void layoutGeneric(String connName) {
    TextField uriField = new TextField("URI", connName, 8000, TextField.ANY | TextField.NON_PREDICTIVE);
    uriField.setInitialInputMode(MidpUtils.LOWERCASE_LATIN);
    form.append(uriField);
  }

  protected void undoLayoutGeneric(int idx) {
    form.delete(idx + 1);
  }

  protected String getGenericValue(int idx) {
    String uri = ((TextField)form.get(idx + 1)).getString();
    return (uri != null ? uri.trim() : "");
  }

  protected void layoutSocket(String connName) {
    String host = connName;
    int port = 0;
    if (connName != null) {
      int idx = connName.indexOf(':');
      if (idx >= 0) {
        host = connName.substring(0, idx);
        port = Utils.parseInt(connName.substring(idx + 1), port);
      }
    }
    TextField hostField = new TextField("Host", host, 2000, TextField.ANY | TextField.NON_PREDICTIVE);
    hostField.setInitialInputMode(MidpUtils.LOWERCASE_LATIN);
    form.append(hostField);
    TextField portField = new TextField("Port", Integer.toString(port), 6, TextField.NUMERIC);
    form.append(portField);
  }

  protected void undoLayoutSocket(int idx) {
    form.delete(idx + 1);
    form.delete(idx + 1);
  }

  protected String getSocketValue(int idx) {
    String host = ((TextField)form.get(idx + 1)).getString();
    String port = ((TextField)form.get(idx + 2)).getString();
    return PREFIX_SOCKET + (host != null ? host.trim() : "") + (port != null ? ':' + port.trim() : "");
  }

  protected void layoutComm(String connName) {
    String[] commPorts = Utils.toStringArray(Utils.split(System.getProperty("microedition.commports"), ","));
    if (commPorts != null) {
      String commPort = connName;
      String commParams = null;
      if (connName != null) {
        int idx = connName.indexOf(';');
        if (idx >= 0) {
          commPort = connName.substring(0, idx);
          commParams = connName.substring(idx + 1);
        }
      }
      ChoiceGroup commPortField = new ChoiceGroup("Port", ChoiceGroup.POPUP, commPorts, null);
      if (commPortField.size() > 0) {
        boolean found = false;
        for (int i = 0; i < commPorts.length; ++i) {
          if (commPorts[i].equals(commPort)) {
            commPortField.setSelectedIndex(i, true);
            found = true;
            break;
          }
        }
        if (!found)
          commPortField.setSelectedIndex(0, true);
      }
      form.append(commPortField);
      TextField commParamsField = new TextField("Params", commParams, 2000, TextField.ANY | TextField.NON_PREDICTIVE);
      commParamsField.setInitialInputMode(MidpUtils.LOWERCASE_LATIN);
      form.append(commParamsField);
    }
  }

  protected void undoLayoutComm(int idx) {
    form.delete(idx + 1);
    form.delete(idx + 1);
  }

  protected String getCommValue(int idx) {
    String port = MidpUtils.getString((ChoiceGroup)form.get(idx + 1));
    port = port != null ? port.trim() : "";
    String params = ((TextField)form.get(idx + 2)).getString();
    params = params != null ? params.trim() : "";
    return PREFIX_COMM + (port.length() > 0 ? port : "") + (params.length() > 0 ? ';' + params : "");
  }

  public void itemStateChanged(Item item) {
    if (item == connTypeChoice) {
      layout(connTypeChoice.getSelectedIndex(), false);
    }
  }
}
